/*
 * AGENT SHERPA
 *  
 * Assignement 2 of the Agent Oriented Software Engineering Course
 * M.Sc. in Advanced Software Engineering (Part-time)
 * University College Dublin www.ucd.ie
 *
 * Copyright (c) 2007 Chris Walsh, Aidan Morrisy and Iain Hull.
 * All rights reserved.
 */

package org.agentsherpa;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.agentsherpa.model.CellType;
import org.agentsherpa.model.Point;

import com.agentfactory.platform.interfaces.Module;

/**
 *
 * @author  Aidan
 */
public class ControlAgentModule extends Module {
    
    private Map<String, String> agents = new HashMap<String,String>();
    private Set<Point> roadCovered;
    private Set<Point> agentRoadVisited;
    
    private Map<Point, CellType> road = new HashMap<Point, CellType>();
    private Map<String,String> agentsToNotify = new HashMap<String,String>();
    
    public void addAgent(String agentName, String address) {
        agents.put(agentName,address);
        System.out.println(" Agent added to AgentMap : " + agentName + " , " +  address );
        
    }
    
   public void removeAgent(String agentName, String address) {
        agents.remove(agentName);
        
    }
    
    public Map<String,String> getAgents(){
        //System.out.println(" AgentMap : " + agents.size() );
        return Collections.unmodifiableMap(agents);
    }
    
    public void addRoadCovered(String agentRoadCovered) {
       String[] roadPoints = agentRoadCovered.split(":");
       for (int i = 0; i < roadPoints.length; i++){
           int comma = roadPoints[i].indexOf(",");
           int x =  Integer.parseInt(roadPoints[i].substring(0,comma));
           int y = Integer.parseInt(roadPoints[i].substring(comma + 1));
           Point p = new Point(x,y);
           agentRoadVisited.add(p);
       }
       
       for (Point agentRoad : agentRoadVisited){
           Boolean inSet = false;
             for (Point point : roadCovered) {
                if (point.equals(agentRoad)) {
                   inSet = true;
                }
            } 
             if (!inSet){
                 roadCovered.add(agentRoad);
             }
       }
    }

	/**
	 * Merge new data into my map.
	 * 
	 * @param data
	 */
	public void mapMerge(String agent, String data) {
		Map<Point, CellType> update = MapUtil.decodeMap(data); 
		MapUtil.mergeMaps(road, update);
		
		try {
			getSimulator().updateKnownRoad(update);
		} catch (PerceptorException e) {
			e.printStackTrace();
		}
	}
	
	public Map<String,String> getAgentsToNotify(String agent) {
            
                //System.out.println("Adding to agents to notify, receieved data from : " + agent);
                agentsToNotify.putAll(agents);
                if (agentsToNotify.isEmpty()){
                    //System.out.println(" No Agents in Agent Map" );                  
                }
                
                agentsToNotify.remove(agent);
               
            
		if (agentsToNotify.isEmpty()) {
			//System.out.println("No Agents to Notify");
			return Collections.emptyMap();
		}
		else {
			System.out.println("Have Agents to Notify");
			Map<String,String> ret = agentsToNotify;
			agentsToNotify = new HashMap<String,String>();
			return ret;
		}
	}
	
	public String getMapData() {
		return MapUtil.encodeMap(road);
	}
	
    private SimulatorService getSimulator() throws PerceptorException {
        SimulatorService simulator = (SimulatorService) agent.getService("org.agentsherpa.SimulatorService");
        if (simulator == null) {
            throw new PerceptorException("Cannot access SimulatorService");
        }
        return simulator;
    }

}